#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#include "gui/gui.h"
#include "utils_image.h"
#include "config.h"
#include "utils.h"

static unsigned int getPixelIndexCW0(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch)
{
    return y * pitch + x;
}

static unsigned int getPixelIndexCW90(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch)
{
    return (height - x) * pitch + y;
}

static unsigned int getPixelIndexCW180(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch)
{
    return (height - y) * pitch + (width - x);
}

static unsigned int getPixelIndexCW270(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch)
{
    return x * pitch + (width - y);
}

void ConvertXRGB8888ToABGR8888(uint32_t *dst, unsigned int dst_w, unsigned int dst_h, unsigned int dst_pitch,
                               uint32_t *src, unsigned int src_w, unsigned int src_h, unsigned int src_pitch,
                               int rotate_cw)
{
    unsigned int max_src_x, max_src_y;
    float scale_x, scale_y;
    int dst_x, dst_y;

    unsigned int (*getPixelIndex)(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch);

    switch (rotate_cw)
    {
    case TYPE_DISPLAY_ROTATE_CW_90:
        getPixelIndex = getPixelIndexCW90;
        max_src_x = src_h - 1;
        max_src_y = src_w - 1;
        scale_x = (float)src_h / dst_w;
        scale_y = (float)src_w / dst_h;
        break;

    case TYPE_DISPLAY_ROTATE_CW_180:
        getPixelIndex = getPixelIndexCW180;
        max_src_x = src_w - 1;
        max_src_y = src_h - 1;
        scale_x = (float)src_w / dst_w;
        scale_y = (float)src_h / dst_h;
        break;

    case TYPE_DISPLAY_ROTATE_CW_270:
        getPixelIndex = getPixelIndexCW270;
        max_src_x = src_h - 1;
        max_src_y = src_w - 1;
        scale_x = (float)src_h / dst_w;
        scale_y = (float)src_w / dst_h;
        break;

    default:
        getPixelIndex = getPixelIndexCW0;
        max_src_x = src_w - 1;
        max_src_y = src_h - 1;
        scale_x = (float)src_w / dst_w;
        scale_y = (float)src_h / dst_h;
        break;
    }

    for (dst_y = 0; dst_y < dst_h; dst_y++)
    {
        // 获取源图像y轴像素位置
        float src_y = (dst_y + 0.5) * scale_y - 0.5;
        unsigned int src_y0 = MAX(0, (int)src_y);
        unsigned int src_y1 = MIN(max_src_y, (int)(src_y + 1));
        float weight_y1 = MAX(0, src_y - src_y0);
        float weight_y0 = 1.0f - weight_y1;

        for (dst_x = 0; dst_x < dst_w; dst_x++)
        {
            // 获取源图像x轴像素位置
            float src_x = (dst_x + 0.5) * scale_x - 0.5;
            unsigned int src_x0 = MAX(0, (int)src_x);
            unsigned int src_x1 = MIN(max_src_x, (int)(src_x + 1));

            // 计算四个临近像素的权重
            float weight_x1 = MAX(0, src_x - src_x0);
            float weight_x0 = 1.0f - weight_x1;

            float weight_00 = weight_x0 * weight_y0;
            float weight_01 = weight_x1 * weight_y0;
            float weight_10 = weight_x0 * weight_y1;
            float weight_11 = weight_x1 * weight_y1;

            // 计算四个临近像素
            uint32_t color_00 = src[getPixelIndex(src_x0, src_y0, src_w, src_h, src_pitch)];
            uint32_t color_01 = src[getPixelIndex(src_x1, src_y0, src_w, src_h, src_pitch)];
            uint32_t color_10 = src[getPixelIndex(src_x0, src_y1, src_w, src_h, src_pitch)];
            uint32_t color_11 = src[getPixelIndex(src_x1, src_y1, src_w, src_h, src_pitch)];

            // 转换四个临近像素为8位R、G、B
            uint8_t r_00 = (color_00 >> 16) & 0xFF;
            uint8_t g_00 = (color_00 >> 8) & 0xFF;
            uint8_t b_00 = (color_00) & 0xFF;

            uint8_t r_01 = (color_01 >> 16) & 0xFF;
            uint8_t g_01 = (color_01 >> 8) & 0xFF;
            uint8_t b_01 = (color_01) & 0xFF;

            uint8_t r_10 = (color_10 >> 16) & 0xFF;
            uint8_t g_10 = (color_10 >> 8) & 0xFF;
            uint8_t b_10 = (color_10) & 0xFF;

            uint8_t r_11 = (color_11 >> 16) & 0xFF;
            uint8_t g_11 = (color_11 >> 8) & 0xFF;
            uint8_t b_11 = (color_11) & 0xFF;

            // 计算双线性插值
            uint8_t a = 0xFF;
            uint8_t r = r_00 * weight_00 + r_01 * weight_01 + r_10 * weight_10 + r_11 * weight_11;
            uint8_t g = g_00 * weight_00 + g_01 * weight_01 + g_10 * weight_10 + g_11 * weight_11;
            uint8_t b = b_00 * weight_00 + b_01 * weight_01 + b_10 * weight_10 + b_11 * weight_11;

            // 将插值色保存到目标
            dst[dst_y * dst_pitch + dst_x] = (a << 24) | (b << 16) | (g << 8) | r;
        }
    }
}

void ConvertRGB565ToABGR8888(uint32_t *dst, unsigned int dst_w, unsigned int dst_h, unsigned int dst_pitch,
                             uint16_t *src, unsigned int src_w, unsigned int src_h, unsigned int src_pitch,
                             int rotate_cw)
{
    unsigned int max_src_x, max_src_y;
    float scale_x, scale_y;
    int dst_x, dst_y;

    unsigned int (*getPixelIndex)(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch);

    switch (rotate_cw)
    {
    case TYPE_DISPLAY_ROTATE_CW_90:
        getPixelIndex = getPixelIndexCW90;
        max_src_x = src_h - 1;
        max_src_y = src_w - 1;
        scale_x = (float)src_h / dst_w;
        scale_y = (float)src_w / dst_h;
        break;

    case TYPE_DISPLAY_ROTATE_CW_180:
        getPixelIndex = getPixelIndexCW180;
        max_src_x = src_w - 1;
        max_src_y = src_h - 1;
        scale_x = (float)src_w / dst_w;
        scale_y = (float)src_h / dst_h;
        break;

    case TYPE_DISPLAY_ROTATE_CW_270:
        getPixelIndex = getPixelIndexCW270;
        max_src_x = src_h - 1;
        max_src_y = src_w - 1;
        scale_x = (float)src_h / dst_w;
        scale_y = (float)src_w / dst_h;
        break;

    default:
        getPixelIndex = getPixelIndexCW0;
        max_src_x = src_w - 1;
        max_src_y = src_h - 1;
        scale_x = (float)src_w / dst_w;
        scale_y = (float)src_h / dst_h;
        break;
    }

    for (dst_y = 0; dst_y < dst_h; dst_y++)
    {
        // 获取源图像y轴像素位置
        float src_y = (dst_y + 0.5) * scale_y - 0.5;
        unsigned int src_y0 = MAX(0, (int)src_y);
        unsigned int src_y1 = MIN(max_src_y, (int)(src_y + 1));
        float weight_y1 = MAX(0, src_y - src_y0);
        float weight_y0 = 1.0f - weight_y1;

        for (dst_x = 0; dst_x < dst_w; dst_x++)
        {
            // 获取源图像x轴像素位置
            float src_x = (dst_x + 0.5) * scale_x - 0.5;
            unsigned int src_x0 = MAX(0, (int)src_x);
            unsigned int src_x1 = MIN(max_src_x, (int)(src_x + 1));

            // 计算四个临近像素的权重
            float weight_x1 = MAX(0, src_x - src_x0);
            float weight_x0 = 1.0f - weight_x1;

            float weight_00 = weight_x0 * weight_y0;
            float weight_01 = weight_x1 * weight_y0;
            float weight_10 = weight_x0 * weight_y1;
            float weight_11 = weight_x1 * weight_y1;

            // 计算四个临近像素
            uint16_t color_00 = src[getPixelIndex(src_x0, src_y0, src_w, src_h, src_pitch)];
            uint16_t color_01 = src[getPixelIndex(src_x1, src_y0, src_w, src_h, src_pitch)];
            uint16_t color_10 = src[getPixelIndex(src_x0, src_y1, src_w, src_h, src_pitch)];
            uint16_t color_11 = src[getPixelIndex(src_x1, src_y1, src_w, src_h, src_pitch)];

            // 转换四个临近像素为8位R、G、B
            uint8_t r_00 = (color_00 & 0xF800) >> 8;
            uint8_t g_00 = (color_00 & 0x07E0) >> 3;
            uint8_t b_00 = (color_00 & 0x001F) << 3;

            uint8_t r_01 = (color_01 & 0xF800) >> 8;
            uint8_t g_01 = (color_01 & 0x07E0) >> 3;
            uint8_t b_01 = (color_01 & 0x001F) << 3;

            uint8_t r_10 = (color_10 & 0xF800) >> 8;
            uint8_t g_10 = (color_10 & 0x07E0) >> 3;
            uint8_t b_10 = (color_10 & 0x001F) << 3;

            uint8_t r_11 = (color_11 & 0xF800) >> 8;
            uint8_t g_11 = (color_11 & 0x07E0) >> 3;
            uint8_t b_11 = (color_11 & 0x001F) << 3;

            // 计算双线性插值
            uint8_t a = 0xFF;
            uint8_t r = r_00 * weight_00 + r_01 * weight_01 + r_10 * weight_10 + r_11 * weight_11;
            uint8_t g = g_00 * weight_00 + g_01 * weight_01 + g_10 * weight_10 + g_11 * weight_11;
            uint8_t b = b_00 * weight_00 + b_01 * weight_01 + b_10 * weight_10 + b_11 * weight_11;

            // 将插值色保存到目标
            dst[dst_y * dst_pitch + dst_x] = (a << 24) | (b << 16) | (g << 8) | r;
        }
    }
}

void ConvertXRGB1555ToABGR8888(uint32_t *dst, unsigned int dst_w, unsigned int dst_h, unsigned int dst_pitch,
                               uint16_t *src, unsigned int src_w, unsigned int src_h, unsigned int src_pitch,
                               int rotate_cw)
{
    unsigned int max_src_x, max_src_y;
    float scale_x, scale_y;
    int dst_x, dst_y;

    unsigned int (*getPixelIndex)(unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned int pitch);

    switch (rotate_cw)
    {
    case TYPE_DISPLAY_ROTATE_CW_90:
        getPixelIndex = getPixelIndexCW90;
        max_src_x = src_h - 1;
        max_src_y = src_w - 1;
        scale_x = (float)src_h / dst_w;
        scale_y = (float)src_w / dst_h;
        break;

    case TYPE_DISPLAY_ROTATE_CW_180:
        getPixelIndex = getPixelIndexCW180;
        max_src_x = src_w - 1;
        max_src_y = src_h - 1;
        scale_x = (float)src_w / dst_w;
        scale_y = (float)src_h / dst_h;
        break;

    case TYPE_DISPLAY_ROTATE_CW_270:
        getPixelIndex = getPixelIndexCW270;
        max_src_x = src_h - 1;
        max_src_y = src_w - 1;
        scale_x = (float)src_h / dst_w;
        scale_y = (float)src_w / dst_h;
        break;

    default:
        getPixelIndex = getPixelIndexCW0;
        max_src_x = src_w - 1;
        max_src_y = src_h - 1;
        scale_x = (float)src_w / dst_w;
        scale_y = (float)src_h / dst_h;
        break;
    }

    for (dst_y = 0; dst_y < dst_h; dst_y++)
    {
        // 获取源图像y轴像素位置
        float src_y = (dst_y + 0.5) * scale_y - 0.5;
        unsigned int src_y0 = MAX(0, (int)src_y);
        unsigned int src_y1 = MIN(max_src_y, (int)(src_y + 1));
        float weight_y1 = MAX(0, src_y - src_y0);
        float weight_y0 = 1.0f - weight_y1;

        for (dst_x = 0; dst_x < dst_w; dst_x++)
        {
            // 获取源图像x轴像素位置
            float src_x = (dst_x + 0.5) * scale_x - 0.5;
            unsigned int src_x0 = MAX(0, (int)src_x);
            unsigned int src_x1 = MIN(max_src_x, (int)(src_x + 1));

            // 计算四个临近像素的权重
            float weight_x1 = MAX(0, src_x - src_x0);
            float weight_x0 = 1.0f - weight_x1;

            float weight_00 = weight_x0 * weight_y0;
            float weight_01 = weight_x1 * weight_y0;
            float weight_10 = weight_x0 * weight_y1;
            float weight_11 = weight_x1 * weight_y1;

            // 计算四个临近像素
            uint16_t color_00 = src[getPixelIndex(src_x0, src_y0, src_w, src_h, src_pitch)];
            uint16_t color_01 = src[getPixelIndex(src_x1, src_y0, src_w, src_h, src_pitch)];
            uint16_t color_10 = src[getPixelIndex(src_x0, src_y1, src_w, src_h, src_pitch)];
            uint16_t color_11 = src[getPixelIndex(src_x1, src_y1, src_w, src_h, src_pitch)];

            // 转换四个临近像素为8位R、G、B
            uint8_t r_00 = (color_00 & 0x7C00) >> 7;
            uint8_t g_00 = (color_00 & 0x03E0) >> 2;
            uint8_t b_00 = (color_00 & 0x001F) << 3;

            uint8_t r_01 = (color_01 & 0x7C00) >> 7;
            uint8_t g_01 = (color_01 & 0x03E0) >> 2;
            uint8_t b_01 = (color_01 & 0x001F) << 3;

            uint8_t r_10 = (color_10 & 0x7C00) >> 7;
            uint8_t g_10 = (color_10 & 0x03E0) >> 2;
            uint8_t b_10 = (color_10 & 0x001F) << 3;

            uint8_t r_11 = (color_11 & 0x7C00) >> 7;
            uint8_t g_11 = (color_11 & 0x03E0) >> 2;
            uint8_t b_11 = (color_11 & 0x001F) << 3;

            // 计算双线性插值
            uint8_t a = 0xFF;
            uint8_t r = r_00 * weight_00 + r_01 * weight_01 + r_10 * weight_10 + r_11 * weight_11;
            uint8_t g = g_00 * weight_00 + g_01 * weight_01 + g_10 * weight_10 + g_11 * weight_11;
            uint8_t b = b_00 * weight_00 + b_01 * weight_01 + b_10 * weight_10 + b_11 * weight_11;

            // 将插值色保存到目标
            dst[dst_y * dst_pitch + dst_x] = (a << 24) | (b << 16) | (g << 8) | r;
        }
    }
}

void ConvertImageToABGR8888(void *dst, unsigned int dst_w, unsigned int dst_h, unsigned int dst_pitch,
                            void *src, unsigned int src_w, unsigned int src_h, unsigned int src_pitch,
                            int src_format, int rotate_cw)
{
    switch (src_format)
    {
    case GUI_PIXEL_FORMAT_X1U5U5U5_1RGB:
        return ConvertXRGB1555ToABGR8888((uint32_t *)dst, dst_w, dst_h, dst_pitch,
                                         (uint16_t *)src, src_w, src_h, src_pitch,
                                         rotate_cw);

    case GUI_PIXEL_FORMAT_U5U6U5_RGB:
        return ConvertRGB565ToABGR8888((uint32_t *)dst, dst_w, dst_h, dst_pitch,
                                       (uint16_t *)src, src_w, src_h, src_pitch,
                                       rotate_cw);
    default:
        return ConvertXRGB8888ToABGR8888((uint32_t *)dst, dst_w, dst_h, dst_pitch,
                                         (uint32_t *)src, src_w, src_h, src_pitch,
                                         rotate_cw);
    }
}